package org.example.netty.socketTest;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.UUID;

@Slf4j
public class SocketServer {

        public static void main(String[] args) {
            new ServerBootstrap()
                    //boss和worker
                    //boss只负责ServerSocketChannel上accept事件，worker只负责socketChannel上的读写
                    .group(new NioEventLoopGroup(),new NioEventLoopGroup(2))
                    .channel(NioServerSocketChannel.class)
                    //boss线程处理accept事件
                    .handler(new ChannelInboundHandlerAdapter() {
                        @Override
                        public void channelActive(ChannelHandlerContext ctx) throws Exception {
                            System.out.println("客户端连接成功");
                        }
                    })
                    //worker线程处理读写事件
                    .childHandler(new ChannelInitializer<NioSocketChannel>() {
                        @Override
                        protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                            nioSocketChannel.pipeline().addLast(
                                    //解码
                                    new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,
                                            0,4,0,4)
                            );
                            //编码
                            nioSocketChannel.pipeline().addLast(new LengthFieldPrepender(4));
                            //解码
                            nioSocketChannel.pipeline().addLast(new StringDecoder(CharsetUtil.UTF_8));
                            //编码
                            nioSocketChannel.pipeline().addLast(new StringEncoder(CharsetUtil.UTF_8));
                            //业务逻辑处理器
                            /*nioSocketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter() {
                                @Override
                                public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                    ByteBuf buf = (ByteBuf) msg;
                                    System.out.println(buf.toString(CharsetUtil.UTF_8));//Charset.defaultCharset()
                                }
                            });*/
                            nioSocketChannel.pipeline().addLast(new SimpleChannelInboundHandler<String>() {
                                @Override
                                protected void channelRead0(ChannelHandlerContext channelHandlerContext, String s) throws Exception {
                                    System.out.println("from client: "+s);
                                    channelHandlerContext.channel().writeAndFlush("from server: "+ UUID.randomUUID());
                                }

                                @Override
                                public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
                                    super.exceptionCaught(ctx, cause);
                                }
                            });

                        }

                        @Override
                        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
                            cause.printStackTrace();
                            ctx.close();
                        }
                    })
                    .bind(8888);

        }
}
